package com.gkj.gulimall.product.javabase;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.SneakyThrows;
import org.springframework.transaction.annotation.Transactional;

import java.io.*;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import java.util.stream.Collectors;


public class Test2 {

}
@Data
@AllArgsConstructor
class User implements Serializable{
    private String name,id,gender;
}
class IOoperation{

    public static void testInputOutput() throws Exception {
        //创建对象序列化输出流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("C:\\Users\\17728\\Desktop\\aa.txt"));
        oos.writeObject(new User("jay","111222","male"));
        //创建对象序列化输入流
        ObjectInputStream ois= new ObjectInputStream(new FileInputStream("C:\\Users\\17728\\Desktop\\aa.txt"));
        User user = (User) ois.readObject();
        System.out.println(user);
        oos.close();
    }
    public static void copyFile(String src, String dist) throws IOException
    {
        FileInputStream in = new FileInputStream(src);//创建字节流对象
        FileOutputStream out = new FileOutputStream(dist);
        byte[] buffer = new byte[20 * 1024];
        // read() 最多读取 buffer.length 个字节
        // 返回的是实际读取的个数
        // 返回 -1 的时候表示读到 eof，即文件尾
        while (in.read(buffer, 0, buffer.length) != -1) {
            out.write(buffer);
        }
        in.close();
        out.close();
    }

    /**
     *
     * @param args
     * @throws Exception
     * InputStreamReader 实现从字节流解码成字符流；
     * OutputStreamWriter 实现字符流编码成为字节流。
     * 编码就是把字符转换为字节，而解码是把字节重新组合成字符
     *
     * 同步 ： 自己亲自出马持银行卡到银行取钱（使用同步IO时，Java自己处理IO读写）。
     * 异步 ： 委托一小弟拿银行卡到银行取钱，然后给你（使用异步IO时，Java将IO读写委托给OS处理，需要将数据缓冲区地址和大小传给OS(银行卡和密码)，OS需要支持异步IO操作API）。
     * 阻塞 ： ATM排队取款，你只能等待（使用阻塞IO时，Java调用会一直阻塞到读写完成才返回）。
     * 非阻塞 ： 柜台取款，取个号，然后坐在椅子上做其它事，等号广播会通知你办理，没到号你就不能去，你可以不断问大堂经理排到了没有，大堂经理如果说还没到你就不能去（使用非阻塞IO时，如果不能读写Java调用会马上返回，当IO事件分发器会通知可读写时再继续进行读写，不断循环直到读写完成）。
     * 套接字用（IP地址：端口号）表示
     */
    public static void main(String[] args) throws Exception {
//        File file = new File("C:\\Users\\17728\\Desktop\\aa.txt");
//        FileReader fileReader = new FileReader(file);
//        BufferedReader bufferedReader = new BufferedReader(fileReader);
//        String line =  null;
//        while ((line = bufferedReader.readLine())!=null){
//            System.out.println(line);
//        }
//        bufferedReader.close();
        testInputOutput();
        BigDecimal bigDecimal = new BigDecimal(11.1);//不会导致精度丢失问题
        bigDecimal.add(new BigDecimal(1.1));

        Queue queue = new ArrayDeque();
        queue.add(1);
        queue.add(2);
        queue.add(3);
        System.out.println(queue.remove());
        System.out.println(queue.remove());
        PriorityQueue<Integer> queue1 = new PriorityQueue<>();
    }
}
class Animal{
    public int id;
    public String name;
    @Override
    public boolean equals(Object obj) {
        Animal animal = (Animal)obj;
        return id == animal.id;
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }

    public static void main(String[] args) {
        Animal animal = new Animal();
        animal.id = 11;
        Animal animal1 = new Animal();
        animal1.id = 12;
        boolean flag = animal.hashCode() == animal1.hashCode();
        System.out.println(animal.equals(animal1));//重写equals方法必须要重写hashcode()
        System.out.println(flag);
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
    }
}

class WaitNotifyExample {
    public synchronized void before() {
        System.out.println("before");
        notifyAll();//只能用在同步方法或者同步控制块中使用
    }

    public synchronized void after() {
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("after");
    }
    //await() signal() signalAll()
    /*
    wait() 是 Object 类的方法，调用对象的 wait() 方法导致当前线程放弃对象的锁（线程暂停执行），
    进入对象的等待池（wait pool），只有调用对象的 notify() 方法（或 notifyAll() 方法）时才能唤醒等待池中的线程进入等锁池（lock pool），
    如果线程重新获得对象的锁就可以进入就绪状态

    程序计数器、虚拟机栈和本地方法栈这三个区域属于线程私有的
     */
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();//创建线程池对象
        WaitNotifyExample example = new WaitNotifyExample();
        executorService.execute(() -> example.after());
        executorService.execute(() -> example.before());
    }
}
//双重校验锁实现对象单例（线程安全）
class Singleton2 {

    private volatile static Singleton2 uniqueInstance;

    private Singleton2() {
    }

    public static Singleton2 getUniqueInstance() {
        //先判断对象是否已经实例过，没有实例化过才进入加锁代码
        if (uniqueInstance == null) {
            //类对象加锁
            synchronized (Singleton.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton2();
                }
            }
        }
        return uniqueInstance;
    }
}

class Single{
    private static Single single;
    static{
        single = new Single();
    }
    private Single(){

    }
    public static Single getSingleInstance(){
        return single;
    }
}
class Test3{
    public static void main(String[] args) {
        System.out.println(Single.getSingleInstance());
        System.out.println(Single.getSingleInstance());
        int i = Math.addExact(1, 2);
        System.out.println(1 & 2);
    }
}

/**
 * 这是一个简单的Runnable类，需要大约5秒钟来执行其任务。
 * @author shuang.kou
 */
class MyRunnable2 implements Runnable {

    private String command;

    public MyRunnable2(String s) {
        this.command = s;
    }


    private void processCommand() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String toString() {
        return this.command;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " Start. Time = " + new Date());
        processCommand();
        System.out.println(Thread.currentThread().getName() + " End. Time = " + new Date());
    }

    public static void main(String[] args) {
        MyRunnable2 myRunnable2 = new MyRunnable2("aa");
        new Thread(myRunnable2).start();
    }
}

class ThreadPoolExecutorDemo {

    private static final int CORE_POOL_SIZE = 5;//定义核心线程数
    private static final int MAX_POOL_SIZE = 10;//最大线程数
    private static final int QUEUE_CAPACITY = 100;
    private static final Long KEEP_ALIVE_TIME = 1L;
    public static void main(String[] args) {

        //使用阿里巴巴推荐的创建线程池的方式
        //通过ThreadPoolExecutor构造函数自定义参数创建
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                CORE_POOL_SIZE,
                MAX_POOL_SIZE,
                KEEP_ALIVE_TIME,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(QUEUE_CAPACITY),
                new ThreadPoolExecutor.CallerRunsPolicy());

        for (int i = 0; i < 10; i++) {
            //创建WorkerThread对象（WorkerThread类实现了Runnable 接口）
            Runnable worker = new MyRunnable2("" + i);
            //执行Runnable
            executor.execute(worker);
        }
        //终止线程池
        executor.shutdown();
        while (!executor.isTerminated()) {
        }
        System.out.println("Finished all threads");
    }
}
//原子类测试
class AtomicIntegerTest {
//    CAS 的原理是拿期望的值和原本的一个值作比较，如果相同则更新成新的值。
    private AtomicInteger count = new AtomicInteger();
    //使用AtomicInteger之后，不需要对该方法加锁，也可以实现线程安全。
    public void increment() {
        count.incrementAndGet();
    }

    public int getCount() {
        return count.get();
    }

    public static void main(String[] args) {
        AtomicIntegerTest atomicIntegerTest = new AtomicIntegerTest();
        atomicIntegerTest.increment();
        int count = atomicIntegerTest.getCount();
        System.out.println(count);
        new Thread().start();
    }
}

//线程池测试
class ExecutorTest{
    public static void main(String[] args) {
        //构造器对象创建线程池对象
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                5,
                10,
                100,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(100),
                new ThreadPoolExecutor.CallerRunsPolicy());
        for(int i = 0;i < 10;i++){
            threadPoolExecutor.execute(()->{//每次开启五个线程来执行该方法
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("当前线程名:"+Thread.currentThread().getName() + " Date: "+new Date());
            });
        }
        threadPoolExecutor.shutdown();
        try {
            threadPoolExecutor.awaitTermination(5000,TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("all thread finished");
    }
}
class Solution {
    public int addDigits(int num) {//各位数相加的和，
        if(num >= 0 && num <= 9)
            return num;
        int sum =0;
        char[] chars = String.valueOf(num).toCharArray();
        for(int i = 0;i < chars.length;i++){
            sum += Integer.parseInt(""+chars[i]);
        }
        return addDigits(sum);
    }
    public static void main(String[] args) {
        System.out.println(new Solution().addDigits(38));
    }
}

class Test4 {
    public static void main(String[] args) {
        try {
            test();
            System.out.println("A");
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("B");
            return;
        } catch (Exception e) {
            System.out.println("C");
        } finally {
            System.out.println("D");
        }
    }

    private static void test() {
        int[] a = {1, 2, 4};
        System.out.println(a[3]);
    }

}
class Main{
    public static void main(String[] args) {
        new Main().sort(new int[]{5,2,3,1});

//        for(int i = 1;i <= 9;i++){
//            for(int j = 1;j <= i;j++){
//                System.out.print(j+" * "+i+" = "+(i * j)+"    ");
//            }
//            System.out.println();
//        ArrayList<Integer> list = new ArrayList();
//        for(int i = 0;i < 12;i++){
//            list.add(i);
//        }
//        bubble2();
//        }

//        Stack<Integer> stack = new Stack();
//        Scanner scanner = new Scanner(System.in);
//        int num = 0;
//        while((num = scanner.nextInt()) != -1){
//            stack.push(num);
//        }
//        while(!stack.isEmpty()){
//            System.out.println(stack.pop() +"   ");
//        }
//        System.out.println(lengthOfLongestSubstring("abcabcbb"));
//        System.out.println(aa(10));
//        List<List<Integer>> list = new Main().threeSum(new int[]{1, 2, 3, 4, 6});
//        list.stream().forEach(li->{
//            System.out.println(li);
//        });
//        int[] sum = new Main().twoSum(new int[]{3,2,4},6);
//        for (int i : sum) {
//            System.out.println(i);
//        }
//        Map<Integer, Integer> map = new HashMap();
    }
    public static void bubble(){
        int arr[] = {22,1,24,4,5,21,23,23};
        int temp = 0;
        for(int i = 0;i < arr.length;i++){//冒泡排序
            for(int j = i;j < arr.length - 1;j++){
                if(arr[i] > arr[j + 1]){
                    temp = arr[j + 1];
                    arr[j + 1] = arr[i];
                    arr[i] = temp;
                }
            }
        }

        for (int a : arr) {
            System.out.println(a);
        }
    }
    public static  void bubble2() {
        int arr[] = {22, 1, 24, 4, 5, 21, 23, 23};
        int l = 0;
        int r = arr.length - 1;
        int target = arr[0];
        while (l < r) {

        }
        for (int i : arr) {
            System.out.println(i);
        }

    }

    public static int findNthDigit (int n) {
        // write code here
        String str = "012345678910";
        ArrayList<Integer> list = new ArrayList<>();
        for(int i = 0;i < str.length();i++){
            list.add(Integer.parseInt(""+str.charAt(i)));
        }
        return list.get(n);
    }

    public void sort(int [] nums){
        sortArray2(nums,0,nums.length - 1);
        for (int i : nums) {
            System.out.println(i);
        }

    }
    public void sortArray(int[] nums,int left,int right) {
        //左指针大于右指针的时候跳出循环
        if(left > right){
            return;
        }
        int target = nums[left];//定义中心轴pivot
        int i = left,j = right;
        while(i < j){
            while(i < j && nums[j] > target)//大于中心轴的数字不需要改变位置，都在右边
                j--;
            nums[i] = nums[j];

            while(i < j && nums[i] < target)
                i++;
            nums[j] = nums[i];
        }
        nums[i] = target;
        sortArray(nums,left,j - 1);
        sortArray(nums,i + 1,right);
    }


    public void test2(){
        ArrayDeque<String> deque = new ArrayDeque<>();
    }
    // TODO: 2022/3/11 快速排序算法 
    public void sortArray2(int[] nums,int left,int right) {//快速排序
        while(left > right){
            return;
        }
        int i = left,j = right;
        int privot = nums[left];//定义中心轴数字
        while(i < j){
            while (i < j && nums[j] > privot)//先移动右指针
                j--;
            nums[i] = nums[j];
            while(i < j && nums[i] < privot)
                i++;
            nums[j] = nums[i];
        }
        nums[i] = privot;
        sortArray2(nums,left,j - 1);
        sortArray2(nums,i + 1,right);
    }
    public static int aa(int n){

        if(n == 1 || n == 0)
            return 1;
//        int b = n * aa(n  -1);
        int a = n * aa(n - 1);
        int b = n + aa(n - 1);
        return a + b;
    }

    public static int lengthOfLongestSubstring (String s) {
        // write code here
        char[] chars = s.toCharArray();
        char c = chars[0];
        int count = 0;
        for(int i = 1;i < chars.length;i++){
            if(c != chars[i]){
                count = count + 1;
            }else{
                count = 0;
                c = chars[i];
            }
        }
        return count;
    }
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> lists = new ArrayList<>();
        List<Integer> list = new ArrayList<>();
        list.add(1);list.add(2);
        lists.add(list);
        return  lists;
    }
    public int[] twoSum(int[] nums, int target) {
        int [] res = new int[2];
        Map<Integer,Integer> map = new HashMap<>();
        for (int i = 0;i < nums.length;i++){
            map.put(nums[i],i);
        }
        for(int i = 0;i < nums.length;i++){
            int n1 = target - nums[i];
            if(map.containsKey(n1)){
                res[0] = i;
                res[1] = map.get(n1);
                return res;
            }
        }
        return res;
    }

}
class ThreadPoolExecutorDemo2{
    public static final int CORE_POOL_SIZE = 5;
    public static final int MAX_POOL_SIZE = 10;
    public static final int QUEUE_CAPATITY = 100;


    public static void main(String[] args) {
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                5, 10, 10, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1),
                new ThreadPoolExecutor.CallerRunsPolicy());//忽视策略

        for(int i = 0;i < 10;i++){
            Runnable runnable = new ThreadDemo();
            threadPool.execute(runnable);
        }
        threadPool.shutdown();
    }
 }
 class ThreadDemo implements Runnable{

    public ThreadDemo(){

    }
     @Override
     public void run() {
         System.out.println(Thread.currentThread().getName() +"Start. TIME"+new Date());
     }
 }
 class ThreadLocalTest{
     public static void main(String[] args) {
         List<Integer> list = new ArrayList();
         list.add(12);
         new ThreadLocalTest().findStr();
         String s = PrintMinNumber(new int[]{3,32,321});
         System.out.println(s);
         int i = NumberOf1Between1AndN_Solution(13);
         System.out.println(i);
         new Thread("t1"){
             @Override
             public void run() {
                 update();
                 update2();
             }
         }.start();
         new Thread("t2"){
             @Override
             public void run() {
                 update();
                 update2();
             }
         }.start();
         new Thread("t3"){
             @Override
             public void run() {
                 update();
                 update2();
             }
         }.start();
     }
     static int age = 10;
     public static ThreadLocal<Integer> initValue = new ThreadLocal(){
         @Override
         protected Integer initialValue() {
             return 10;
         }
     };
     public static void update(){
         initValue.set(initValue.get() + 100);
         System.out.println(initValue.get());
     }
     public static void update2(){
         age += 10;
         System.out.println(age);
     }

     public static int NumberOf1Between1AndN_Solution(int n) {
         if (n == 0)
             return 0;
         if (n <= 10)
             return 2;
         int cnt = 0;String str = "";
         List<Integer> list = new ArrayList();
         for(int i = 1;i <= n;i++){
             str += ""+i;
         }
         char[] chars = str.toCharArray();
         for(int i = 0;i < chars.length;i++){
             if(chars[i] == '1')
                 cnt++;
         }
         return cnt++;
     }

     //把数组排成最小的数
     public static String PrintMinNumber(int [] numbers) {
         int n = numbers.length;
         String [] nums = new String[n];
         for(int i = 0;i < n;i++){
             nums[i] = numbers[i]+"";
         }
         Arrays.sort(nums,(v1,v2)->{//比较相加字符串的大小，确定是否要交换位置
             return (v1+v2).compareTo(v2+v1);
         });

         StringBuilder builder = new StringBuilder();
         for (String str : nums) {
             builder.append(str);
         }
         return builder.toString();
     }

     public void findStr(){
         int cnt = 0;
         String str = "aafgegaa";
         HashMap<Character,Integer> map = new HashMap();
         map.put('e',0);
         for(int i = 0;i < str.length();i++){
             if(map.containsKey(str.charAt(i)))
                 map.put('e',++cnt);
         }
         System.out.println(cnt);
     }

 }
 class crossThread implements Runnable{

    //线程交替打印123
     public static void main(String[] args) {
         crossThread cross = new crossThread();

         new Thread(cross,"t1"){
             @SneakyThrows
             @Override
             public void run() {
                 synchronized (cross){
                     cross.wait();//线程释放锁，等待当前线程某个方法唤醒
                     System.out.println(1);
                 }
             }
         }.start();
         new Thread(cross,"t2"){
             @Override
             public void run() {
                 synchronized (cross){
                     cross.notifyAll();//notify不释放锁
                     System.out.println(2);
                     System.out.println(3);
                 }
             }
         }.start();
     }


     @Override
     public void run() {
         System.out.println(1);
     }
 }
 @Data
// @AllArgsConstructor
 class Person{
//    private int id,age;
//    private String name;
//    public Person(int id){
//        this.id = id;
//    }
    static int []arr = new int[]{11,2,4,555,35,1};
     static int left = 0,right = arr.length - 1;
     public static void quickSort(int []arr,int left,int right){
         int l = left,r = right;
         while(l > r){
             return;
         }
         int privot = arr[0];
         while(l < r){
             while(l < r && arr[l] < privot){
                 l++;
             }
             arr[r] = arr[l];
             while(l < r && arr[r] > privot){//大于中枢变量就不用改变位置
                 r--;
             }
             arr[l] = arr[r];
         }
         arr[l] = privot;
         quickSort(arr,left,r--);
         quickSort(arr,l++,right);
     }


     public static void main(String[] args){
         quickSort(arr,left,right);
         for (Integer integer : arr) {
             System.out.println(integer);
         }

         List<Person> list = new ArrayList<>();
        for(int i = 0;i < 10;i++){
//            list.add(new Person(i,(i + 1),"p"+i));
        }
//         List<Person> collect = list.stream().filter((l) -> {
//             return l.id == 1;
//         }).collect(Collectors.toList());

     }

 }

 @Data
 class Room{
    private Integer currentPlayerNumber;
    private Integer PlayerNumber;
 }

 class TestRoom{
     public static void main(String[] args) {
         List<Room> list = new ArrayList<>();
         for(int i = 0;i < 10;i++){
             Room room = new Room();
             room.setPlayerNumber(i + 1);
             room.setCurrentPlayerNumber(i + 1);
             list.add(room);
         }
         List<Room> collect = list.stream().sorted((r1, r2) -> {
             if (r2.getCurrentPlayerNumber() - r1.getPlayerNumber() == 0) {
                 return 1;
             } else if (r1.getPlayerNumber() - r2.getPlayerNumber() > 0) {
                 return -1;
             } else if(r1.getCurrentPlayerNumber() == 0 && r2.getCurrentPlayerNumber() == 0){

             }
                 return 0;
         }).collect(Collectors.toList());
         for (Room room : collect) {
             System.out.println(room);
         }

     }
 }







